Skip to content

fix(chat): retain live work during transient progress storage failure - #8366

Merged
loopx-agent merged 3 commits into
mainfrom
codex/chat-persistence-pressure-20261108
Nov 8, 2026
Merged

loopx-agent merged 3 commits into
mainfrom
codex/chat-persistence-pressure-20261108

Conversation

@loopx-agent

@loopx-agent loopx-agent commented Nov 8, 2026 •

Copy link
Copy Markdown
Collaborator

Streaming Chat work can be abandoned when saving an ancillary progress timestamp fails with ENOSPC. The provider may already have executed tools, so replaying the original request is unsafe.

Defer only that metadata checkpoint, retain its dirty state and use the existing retry interval. First require the primary event journal to persist: a full journal still fails instead of accumulating an unbounded in-memory backlog. Mandatory start/close writes and other filesystem errors keep their failure behavior. This reuses the existing buffer, File store and execution owner; it adds no model call, queue, protocol, setting or frontend surface.

Validation at the final head:

  • 591 runtime/event-buffer/activation/preparation tests passed, including twelve rename-fault cases across Turn and Session metadata: temporary pressure, full storage at close, journal failure, permission errors, mandatory identity writes and concurrent stop. Full-answer readback and the separate following request are verified without replay.
  • 422 existing private-conversation tests passed.
  • Four isolated real HTTP + native-protocol + File-store cases passed. Both no-fault cases have identical normalized base/head observations; both injected-rename cases fail on immutable base fe36f31fdedd9e5ad804e73be251c473b0e60007 and return the complete answer on the final head. Each original request starts the synthetic provider exactly once, and its independent follow-up completes.
  • The same final twelve-case fixture has six failures and six passing negative cases on that immutable base. No paid model calls or production fault injections.
  • Standard premerge passed all six direct and thirteen selected checks, with no failures or warnings; Ruff, compile, diff and bilingual checks passed.

The initial premerge failures remain recorded. The inherited runtime ceiling is settled exactly from 2,475 to 2,488 lines for the thirteen error-boundary lines. The unchanged private-conversation owner already exceeded the default at 2,012 lines on the base; its verified thread-identity change from #8289 was inspected and its existing suite passed, so this diff records only that exact line ceiling. Global defaults, type metrics, production Lark code and frozen acceptance criteria remain unchanged.

The bounded refactoring pass found no useful extraction beyond the existing checkpoint owner. This mitigates progress-metadata pressure; physical disk exhaustion, persistent journal failure, historical failed work and installed-service adoption remain separate operational concerns.

Signed-off-by: LoopX Agent <337587101+loopx-agent@users.noreply.github.com>
Signed-off-by: LoopX Agent <337587101+loopx-agent@users.noreply.github.com>
Signed-off-by: LoopX Agent <337587101+loopx-agent@users.noreply.github.com>

@loopx-agent loopx-agent left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewer: model_agent · gpt-6.1-sol · OpenAI · runtime_reported · reasoning_effort=max(作者自审,非独立人工评审)

Approval conclusion (author-owned PR; GitHub blocks formal self-approval)

当前精确 head:561f7816ef7e1a39ec6a28508261fcee130adcaf。无阻塞 finding;以下结论只覆盖本 PR 的工程行为。

动机 / Motivation

正在等待原生 Chat 完整答复的用户。同一请求已经开始执行,随后保存进度时间遇到 ENOSPC;旧版本结束该回合,新版本在事件日志已落盘时继续并返回完整答案。重问可能重复已执行工具;直接丢弃原问题又留下缺答。
隔离 HTTP 路径读回完整答案,原请求仅启动一次上游,下一条独立请求仍能完成。本 PR 不清理磁盘、不重放历史失败、不改变权限或安装策略,也不声称生产服务已经采用。真实磁盘耗尽原因、持续日志写入失败及历史未知效果仍需各原责任路径核验。

改动思路 / Approach

进度快照属于可延后的投影;执行身份、主事件日志与最终落盘仍是必须成功的边界,职责保持在原缓冲器和 File owner。当前 PR 只修复进度元数据写入的失败传播,并保留主日志、身份、关闭与停止保护;不扩展为磁盘清理、全局重试或第二执行链。
执行入口仍是原 HTTP Chat 请求、受管队列和 _run_started_turn.event_sink。这次没有扩大全局原子写入重试,而是在已负责进度节流的原缓冲器区分非强制进度快照与必须成功的持久化;已有 dirty 标记保留,下一次沿原间隔重试。没有新状态、配置、模型调用或用户确认步骤。

评审曾反证“只吞掉元数据错误即可”:若主事件日志也写不进去,会形成只在内存里的积压。因此最终 head 先同步核实主日志持久化;该步骤失败仍交原监督收尾。相比新增恢复执行链,这个边界更小,也更容易回滚。

具体改动 / Changes

依据:会话交付 RFC,spec_ref 为 docs/architecture/rfcs/app-conversation-and-async-inbox-v0.md,spec_revision 为 fe36f31fdedd9e5ad804e73be251c473b0e60007,使用改动前已接受的合同。

  • criterion_id:One authorized driver performs the work。本切片 implemented:同一原请求只有一次 provider start,当前执行不因辅助快照失败重放;强制落盘、日志失败、权限及 stop 的负例仍受原 owner 控制。
  • criterion_id:The draft opens in the original App conversation。完整生产 App/真实模型层 deferred;本次真实 File、HTTP 原会话全文与独立 store 读回通过,不能据此宣称整个 G0/R3 或已安装服务验收完成。

关键代码讲解

_TurnEventBuffer._checkpoint_locked 仍按既有间隔保存同一 Turn/Session。只有非 force 的 ENOSPC 才进入延后分支;首先调用原 flush_events,成功后保留 dirty 并更新时间节流,其他错误直接抛出。

_TurnEventBuffer.close 保留 force=True,最终主日志和快照不能被这条容错路径绕过。十二种故障断言 从真实文件写入、原执行次数、最终正文、独立后续请求及停止状态判断结果,而不让 mock 直接提供“已持久化”结论。

模块体积从 2475 精确记录至 2488 行;不是压缩关键语义或提高全局限额。原主干 private_conversations.py 的 2012 行超限在不可变 base 也复现;本 PR 不改其源码,核过 #8289 的线程身份差异并跑通其 422 项既有测试,仅记录精确行数。其他类型指标、默认限额和冻结验收不动。

对主干的风险 / Risks

主风险是把短暂的辅助写入失败错误地推广成“任意存储失败都继续”。最终实现以可持久化的主事件日志为前提;journal-space、identity-space、full-at-close、EACCES 和 concurrent stop 均有反例,不能借此产生完成或重复执行。持续满盘、进程崩溃后的真实效果仍归原监督与效果对账,不由本 PR 猜测恢复。

PASS:最终运行时/缓冲/激活/准备回归 591 项,既有 Lark 回归 422 项;真实 HTTP + native 协议 + File 的四组对照通过。正常两组 base/head 指纹相同,两个 ENOSPC 分支在 base 缺答、head 完整回答;每个原请求启动一次合成 provider,后续独立输入完成。相同十二例在不可变 base 为六失败/六通过;失败历史保留。

PASS:标准 premerge 六 direct、十三 selected,Ruff、compile、diff、双语检查。模型输出和故障注入均为隔离合成,不使用生产记录或付费模型。当前 Goal 明确 wait_for_ci=false,未查询、等待或用 CI 替代必要本地证据。

语义与 CI 对齐

复用既有 errno、Core 状态和持久化 owner,无新增共享 vocabulary、actor 或权限。默认行为变化已在 PR 正文与本 review 明说;没有 default-off/opt-in 宣称。预算失败按相同源码、度量与 base 对照核实后精确结算,不把旧失败改称历史通过。没有改 agent 指令、可接受输入、来源拒绝或工作义务。

我的整体评价 / Verdict

本 PR 是 justified_increment:已有真实 caller、可复现缺答、可验证的原回合完整结果和保守失败边界,未以小补丁代替原服务采用与历史消息闭环。long_horizon=preserved,user_experience=improved,仅指已验证的运行与 HTTP 工程路径;没有额外让用户重问或重新授权。

只改 _TurnEventBuffer 的内部错误处理;原 Chat 正文、状态字段、组件、布局和设置未改变。未进行生产满盘注入、真实模型或已安装原生 App 视觉验收。
必要代码留在既有 owner;额外模块提取和并行恢复框架均无收益,bounded refactoring 判定 unnecessary。剩余最大验证缺口是生产储存根因、正常部署后的原服务采用及实际原消息结果;这些保持明确,不把本 review 当作相应业务完成。

English verdict: APPROVE 561f781. Ancillary metadata ENOSPC preserves the original live work only after durable event flush; critical persistence and stop remain enforced. Exact-head local and real HTTP/File counterfactuals pass; production adoption is separate.

@loopx-agent
loopx-agent merged commit 3628930 into main Nov 8, 2026
6 of 7 checks passed
@loopx-agent
loopx-agent deleted the codex/chat-persistence-pressure-20261108 branch November 8, 2026 11:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant